﻿using System;
using System.Drawing;
using System.Collections.Generic;
using System.IO;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;

using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint.WebControls;

using SO.SharePoint.Utilities;
using SO.SharePoint.Utilities.Logging;

namespace SO.SharePoint.WebParts.Layouts.SO
{
    public partial class LogViewer : LayoutsPageBase
    {
        private LogReader _reader;

        protected void Page_Load(object sender, EventArgs e)
        {
            try
            {
                LoadServerList();
                LoadFilterableFields();
            }
            catch (Exception ex)
            {
                errorLabel.Text = "Error loading servers in farm";
            }
        }

        private void LoadFilterableFields()
        {
            if (!Page.IsPostBack)
            {
                filterFieldDropDown.Items.Add(new ListItem("Category", "Category"));
                filterFieldDropDown.Items.Add(new ListItem("Correlation", "Correlation"));
                filterFieldDropDown.Items.Add(new ListItem("Level", "Level"));
            }
        }

        private void LoadServerList()
        {
            try
            {
                if (!Page.IsPostBack)
                {
                    ListItem item;

                    foreach (SPServer server in SPFarm.Local.Servers)
                    {
                        item = new ListItem(server.DisplayName, server.Id.ToString());

                        if (server.DisplayName == Environment.MachineName)
                            item.Selected = true;

                        serverDropDown.Items.Add(item);
                    }
                }
            }
            catch (Exception ex)
            {
                Logging.WriteException(ex);
                throw new Exception("Error loading server list", ex);
            }
        }

        private void BindData(List<LogEntry> list)
        {
            EventGrid.DataSource = list;
            EventGrid.AutoGenerateColumns = false;
            EventGrid.ItemDataBound += new DataGridItemEventHandler(EventGrid_ItemDataBound);

            BoundColumn col = new BoundColumn();
            col.DataField = "TimeStamp";
            col.Visible = true;
            col.HeaderText = col.DataField;
            EventGrid.Columns.Add(col);

            col = new BoundColumn();
            col.DataField = "Process";
            col.Visible = false;
            col.HeaderText = col.DataField;
            EventGrid.Columns.Add(col);

            col = new BoundColumn();
            col.DataField = "Tid";
            col.Visible = false;
            col.HeaderText = col.DataField;
            EventGrid.Columns.Add(col);

            col = new BoundColumn();
            col.DataField = "Area";
            col.Visible = false;
            col.HeaderText = col.DataField;
            EventGrid.Columns.Add(col);

            col = new BoundColumn();
            col.DataField = "Category";
            col.Visible = true;
            col.HeaderText = col.DataField;
            EventGrid.Columns.Add(col);

            col = new BoundColumn();
            col.DataField = "EventId";
            col.Visible = false;
            col.HeaderText = col.DataField;
            EventGrid.Columns.Add(col);

            col = new BoundColumn();
            col.DataField = "Level";
            col.Visible = true;
            col.HeaderText = col.DataField;
            EventGrid.Columns.Add(col);

            col = new BoundColumn();
            col.DataField = "Message";
            col.Visible = true;
            col.HeaderText = col.DataField;
            EventGrid.Columns.Add(col);

            col = new BoundColumn();
            col.DataField = "Correlation";
            col.Visible = true;
            col.HeaderText = col.DataField;
            EventGrid.Columns.Add(col);

            EventGrid.HeaderStyle.Font.Bold = true;
            EventGrid.HeaderStyle.Font.Size = FontUnit.Larger;
            EventGrid.HeaderStyle.BackColor = Color.Black;
            EventGrid.HeaderStyle.ForeColor = Color.White;

            EventGrid.DataBind();
        }

        private void LoadEvents(string filename)
        {
            try
            {
                _reader = new LogReader(filename);
                _reader.Parse();

                BindData(_reader.Entries);

                filterStatusLabel.Text = string.Format("Log file not filtered. {0} item(s) found.", _reader.Entries.Count);
            }
            catch (Exception ex)
            {
                Logging.WriteException(ex);
                throw new Exception("Error loading events.", ex);
            }
        }

        void EventGrid_ItemDataBound(object sender, DataGridItemEventArgs e)
        {
            if (e.Item.DataItem != null)
            {
                switch (((LogEntry)e.Item.DataItem).Level.ToUpper())
                {
                    case "MEDIUM":
                        e.Item.BackColor = Color.Yellow;
                        break;

                    case "HIGH":
                        e.Item.BackColor = Color.Orange;
                        break;

                    case "CRITICAL":
                        e.Item.BackColor = Color.OrangeRed;
                        break;

                    case "UNEXPECTED":
                        e.Item.BackColor = Color.Red;
                        e.Item.ForeColor = Color.White;
                        break;
                }
            }
        }

        private void LoadFiles(string servername)
        {
            try
            {
                string path = string.Empty;

                if (servername == Environment.MachineName)
                {
                    path = SPDiagnosticsService.Local.LogLocation;

                    if (path.Contains("%CommonProgramFiles%"))
                        path = path.Replace("%CommonProgramFiles%", Environment.GetFolderPath(Environment.SpecialFolder.CommonProgramFiles));
                }
                else
                {
                    throw new NotImplementedException();
                }

                string[] files = Directory.GetFiles(path, "*.log");

                foreach (string f in files)
                {
                    filesDropDown.Items.Add(new ListItem(f));
                }
            }
            catch (Exception ex)
            {
                Logging.WriteException(ex);
                errorLabel.Text = "Can't load file list.";
            }
        }

        protected void selectServerButton_Click(object sender, EventArgs e)
        {
            try
            {
                LoadFiles(serverDropDown.SelectedItem.Text);

                filterPanel.Visible = false;
            }
            catch (Exception ex)
            {
                errorLabel.Text = "Error loading files from server.";
            }
        }

        protected void selectFileButton_Click(object sender, EventArgs e)
        {
            try
            {
                LoadEvents(filesDropDown.SelectedItem.Text);

                filterPanel.Visible = true;
            }
            catch (Exception ex)
            {
                errorLabel.Text = "Error loading events from file or invalid ULS file";
            }
        }

        protected void filterLogButton_OnClick(object sender, EventArgs e)
        {
            try
            {
                _reader = new LogReader(filesDropDown.SelectedItem.Text);
                _reader.Parse();

                if (_reader != null)
                {
                    switch (filterFieldDropDown.SelectedItem.Value)
                    {
                        case "Category":
                            _reader.Filter(FilterableLogFields.Category, filterValueText.Text);
                            break;

                        case "Correlation":
                            _reader.Filter(FilterableLogFields.Correlation, filterValueText.Text);
                            break;

                        case "Level":
                            _reader.Filter(FilterableLogFields.Level, filterValueText.Text);
                            break;                        
                    }                    
                }

                if (_reader.FilterResult != null)
                    BindData(_reader.FilterResult);                

                filterStatusLabel.Text = string.Format("Log file filtered ('{0}'='{1}'). Result: {2} item(s) found.", filterFieldDropDown.SelectedItem.Value, 
                    filterValueText.Text, _reader.FilterResult.Count);

                filterValueText.Text = string.Empty;
                clearFilterButton.Enabled = true;
            }
            catch (Exception ex)
            {
                errorLabel.Text = "Error while filtering log.";
            }
        }        
    }
}
